/**
 * This class represents a product
 * 
 * @author Konrad Paumann
 * @author Bernhard Denner
 * @author Maximilian Csuk
 * 
 * $Revision: 85 $ 
 * $Date: 2007-10-25 06:20:31 +0000 (Thu, 25 Oct 2007) $
 * 
 */

public class Product implements Displayable {
	/**
	 * variables
	 */
	private String shortDescription;
	private String description;
	private int price;
	private int amount;
	private Unit ProductUnit;

	/**
	 * checks, if a price is valid
	 * 
	 * @param price
	 * @return price valid?
	 */
	private boolean priceValid(int price) {
		return price > 0;
	}

	/**
	 * checks, if the product's price is valid
	 * 
	 * @return price valid?
	 */
	private boolean priceValid() {
		return priceValid(price);
	}

	/**
	 * checks, if an amount is valid
	 * 
	 * @param amount
	 * @return amount valid?
	 */
	private boolean amountValid(int amount) {
		return amount >= 0;
	}

	/**
	 * checks, if the product's amount is valid
	 * 
	 * @return amount valid?
	 */
	private boolean amountValid() {
		return amountValid(amount);
	}

	/**
	 * checks, if a short-description is valid
	 * 
	 * @param shortDescription
	 * @return short-description valid?
	 */
	private boolean shortDescriptionValid(String shortDescription) {

		// check shortdescription with regular expressions
		return shortDescription.matches("[A-Z0-9 ]{10}");
	}

	/**
	 * checks, if the product's short-description is valid
	 * 
	 * @return shortDescription valid?
	 */
	private boolean shortDescriptionValid() {
		return shortDescriptionValid(shortDescription);
	}

	/**
	 * constructor
	 * 
	 * @param shortDescription
	 *            unique short-description of the product (10 characters max)
	 * @param description
	 *            description of the product
	 * @param price
	 *            price in cent
	 * @param amount
	 *            the current amount
	 * @throws ProductException
	 */
	public Product(String shortDescription, String description, int price,
			int amount) throws ProductException {

		// check the short-description
		if (!shortDescriptionValid(shortDescription))
			throw new ProductException("Kurzbezeichnung ist nicht korrekt!");

		// check the price
		if (!priceValid(price))
			throw new ProductException("Preis ist nicht korrekt!");

		// check the amount
		if (!amountValid(amount))
			throw new ProductException("Stueckzahl ist nicht korrekt!");

		this.shortDescription = shortDescription;
		this.description = description;
		this.price = price;
		this.amount = amount;
		this.ProductUnit = new Unit("Stueck", 1);
	}
	
	
	/**
	 * constructor to create Product from restore string
	 * restore string: "sdescription:price:amount:description\\unitdata"
	 * @param ProductLine
	 * @throws ProductException
	 */
	public Product(String ProductLine) throws ProductException {
		String[] ProductLineSplit = ProductLine.split("\\\\");
		String[] ProductArgs = ProductLineSplit[0].split(":");
		
		// check the short-description
		if (!shortDescriptionValid(ProductArgs[0]))
			throw new ProductException("Kurzbezeichnung ist nicht korrekt!");

		// check the price
		if (!priceValid(Integer.parseInt(ProductArgs[1])))
			throw new ProductException("Preis ist nicht korrekt!");

		// check the amount
		if (!amountValid(Integer.parseInt(ProductArgs[2])))
			throw new ProductException("Stueckzahl ist nicht korrekt!");
		
		this.shortDescription = ProductArgs[0];
		this.description = ProductArgs[3];
		this.price = Integer.parseInt(ProductArgs[1]);
		this.amount = Integer.parseInt(ProductArgs[2]);
		this.ProductUnit = new Unit(ProductLineSplit[1]);
	}

	/**
	 * returns the description
	 * 
	 * @return description
	 */
	public String getDescription() {
		return description;
	}

	/**
	 * set the description
	 * 
	 * @param description
	 */
	public void setDescription(String description) {
		this.description = description;
	}

	/**
	 * returns the short-description
	 * 
	 * @return shortDescription
	 */
	public String getShortDescription() {
		return shortDescription;
	}

	/**
	 * returns the amount
	 * 
	 * @return amount
	 */
	public int getAmount() {
		return amount;
	}
	
	public int getAmount(String unitName) 
			throws ProductException {
		return getAmount() * ProductUnit.getFactor(unitName);
	}
		
	/**
	 * sets the amount
	 * 
	 * @param amount
	 */
	public void setAmount(int amount) throws ProductException {
		if (!amountValid(amount))
			throw new ProductException("Stueckzahl nicht korrekt!");
		this.amount = amount;
	}
	
	/**
	 * sets the amount with the specified unit
	 * @param amount
	 * @param unitName
	 * @throws ProductException
	 */
	public void setAmount(int amount, String unitName)
			throws ProductException {
		setAmount(amount * ProductUnit.getFactor(unitName));
	}

	/**
	 * returns the price
	 * 
	 * @return price
	 */
	public int getPrice() {
		return price;
	}

	/**
	 * sets the price
	 * 
	 * @param price
	 */
	public void setPrice(int price) throws ProductException {
		if (!priceValid(price))
			throw new ProductException("Verkaufspreis nicht korrekt!");
		this.price = price;
	}

	/**
	 * alters the amount
	 * 
	 * @param amount
	 */
	public void alterAmount(int amount) throws ProductException {
		if (!amountValid(this.amount + amount))
			throw new ProductException("Stueckzahl nicht korrekt!");
		this.amount += amount;
	}
	
	/**
	 * changes the amount relativly with the help of a unit
	 * @param amount
	 * @param unitName
	 * @throws ProductException
	 */
	public void alterAmount(int amount, String unitName)
			throws ProductException {
		alterAmount(amount * ProductUnit.getFactor(unitName));
	}
	
	
	/**
	 * Adds a product unit to the unit chain
	 * 
	 * @param unitName
	 * @param unitFactor
	 * @param parentUnit
	 * @throws ProductException
	 */
	public void addProductUnit(String unitName, int unitFactor, String parentUnit) 
			throws ProductException {
		ProductUnit.addUnit(unitName, unitFactor, parentUnit);
	}
	
	/**
	 * removes a product unit from the unit chain
	 * @param unitName
	 * @throws ProductException
	 */
	public void removeProductUnit(String unitName) 
			throws ProductException {
		ProductUnit = ProductUnit.removeUnit(unitName);
	}
	
	
	/**
	 * gets the string to be displayed
	 * @return String with product-details
	 */
	public String getDisplayString() {
		return (String)getShortDescription() + "\t" + getPrice() + "\t" +
				getDescription() + "\t" + getAmount() + " " + ProductUnit.getDisplayString();
	}
	
	/**
	 * 
	 * @return String: returns restore string with Product data and Unit data
	 */
	public String save() {
		return getShortDescription() + ":" + getPrice() + ":" + 
					getAmount() + ":" + getDescription() + "\\" + ProductUnit.save();
	}
	
}
